/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.
 */
package es.silenus.detecta.dao.impl;

import es.silenus.detecta.dao.UserDAO;

import es.silenus.detecta.model.Role;
import es.silenus.detecta.model.User;

import org.hibernate.FetchMode;
import org.hibernate.Session;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;


/**
 * User DAO implementation.
 *
 * @author <a href="mailto:malonso@silenus-consultoria.es">Mariano Alonso</a>
 *
 * @since 25-mar-2009 17:56:59
 */
public class UserDAOImpl extends ReadWriteDAOImpl<User, Integer> implements UserDAO {
	/**
	 * Finds a user by its login.
	 *
	 * @param login the login.
	 *
	 * @return the user or null.
	 */
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public User findByLogin(final String login) {
		Session session = null;

		try {
			session = getSession();

			return (User)session.getNamedQuery(User.class.getName() + ".findByLogin").setString("login", login).uniqueResult();
		} finally {
			releaseSession(session);
		}
	}

	/**
	 * Finds a user by its user and password.
	 *
	 * @param login the login.
	 * @param password the password encoded/hashed as in database.
	 *
	 * @return the user or null.
	 */
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public User findByLoginAndPassword(final String login, final String password) {
		Session session = null;

		try {
			session = getSession();

			return (User)session.getNamedQuery(User.class.getName() + ".findByLoginAndPassword").setString("login", login)
													.setString("password", password).uniqueResult();
		} finally {
			releaseSession(session);
		}
	}

	/**
	 * Retrieves the organization administrators.
	 *
	 * @param organization the organization.
	 *
	 * @return the list of administrators.
	 */
	@SuppressWarnings({"unchecked"})
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<User> getAdministrators(int organization) {
		Session session = null;

		try {
			session = getSession();

			return session.getNamedQuery(User.class.getName() + ".getAdministrators")
										.setInteger("organizationId", organization)
										.setParameter("role", Role.ROLE_ORGANIZATION_ADMINISTRATOR).list();
		} finally {
			releaseSession(session);
		}
	}

	/**
	 * Override this method to provide a find by example page criteria.
	 *
	 * @param criteria the criteria.
	 * @param object the sample object.
	 *
	 * @return the criteria.
	 */
	protected DetachedCriteria preparePageCriteria(final DetachedCriteria criteria, final Map<String, Object> object) {
		criteria.setFetchMode("role", FetchMode.JOIN);
		criteria.setFetchMode("organization", FetchMode.JOIN);

		Object temp = object.get("id");

		if(temp != null) {
			criteria.add(Restrictions.eq("id", temp));
		}

		temp = object.get("login");

		if(temp != null) {
			criteria.add(Restrictions.ilike("login", (String)temp, MatchMode.ANYWHERE));
		}

		temp = object.get("fullname");

		if(temp != null) {
			criteria.add(Restrictions.ilike("fullname", (String)temp, MatchMode.ANYWHERE));
		}

		temp = object.get("email");

		if(temp != null) {
			criteria.add(Restrictions.ilike("email", (String)temp, MatchMode.ANYWHERE));
		}

		temp = object.get("language");

		if(temp != null) {
			criteria.add(Restrictions.eq("language", temp));
		}

		temp = object.get("role");

		if(temp != null) {
			criteria.add(Restrictions.eq("role", temp));
		}

		temp = object.get("organization.id");

		if(temp != null) {
			criteria.add(Restrictions.eq("organization.id", temp));
		}

		temp = object.get("disabled");

		if(temp != null) {
			criteria.add(Restrictions.isNotNull("disableDate"));
		}

		return criteria;
	}
}
